package com.tinem.platform.web.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.tinem.platform.module.pojo.co.GatewayHeadName;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.module.pojo.enums.security.EncryptionAlgorithm;
import com.tinem.platform.module.pojo.vo.error.UserException;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.web.gateway.util.GatewayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className ChannelScopeGatewayFilterFactory
 * @description 客户端请求签名
 * @site 
 * @company 
 * @create 2020-07-03 12:26
 */
@Slf4j
@Component
public class ClientReqCryptoGatewayFilterFactory extends ModifyRequestBodyGatewayFilterFactory {
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    @SuppressWarnings("unchecked")
    public GatewayFilter apply(ModifyRequestBodyGatewayFilterFactory.Config c) {
        Config config = new Config();
        config.setRewriteFunction(String.class,String.class,(exchange,reqBody)-> {
            String client = GatewayUtil.getClient(exchange);
            String clientRedisKey = RedisKeyEnum.client_info.getKey(client);// 缓存中上传请求签名类型

            // 缓存中客户端请求是否加密
            String  reqCrypto = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqCrypto");
            if(!Boolean.parseBoolean(reqCrypto)){
                return Mono.just(reqBody);
            }

            // 缓存中请求的加密类型
            String  reqCryptoType = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqCryptoType");
            // 客户端上传加密类型
            String  clientReqCryptoType = exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_CRYPTO_TYPE);
            if(!StrUtil.equals(reqCryptoType,clientReqCryptoType)){
                // 请求加密类型不匹配
                throw new UserException(MessageCode.ERROR_PLATFORM_CLOUD_WEB_GATEWAY_CRYPTO_TYPE,reqCryptoType,clientReqCryptoType);
            }
            // 缓存中请求解密证书
            String reqCryptoPuk = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqCryptoPuk");
            // 缓存中请求解密KEY
            String reqCryptoKey = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqCryptoKey");
            // 缓存中请求解密IV
            String reqCryptoIv = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqCryptoIv");
            String body = EncryptionAlgorithm.valueOf(reqCryptoType).decrypt(reqCryptoKey,reqCryptoIv,reqCryptoPuk,reqBody);

            return Mono.just(body);
        });
        return super.apply(config);
    }
}
